package org.baitu.zzim.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.RequiredArgsConstructor;
import org.baitu.zzim.config.NettyProperties;
import org.baitu.zzim.decoder.MessageDecoder;
import org.baitu.zzim.decoder.MessageEncoder;
import org.baitu.zzim.decoder.WebSocketFrameToByteBufDecoder;
import org.baitu.zzim.decoder.WebSocketProtobufEncoder;
import org.baitu.zzim.handler.JwtHandshakeAuthHandler;
import org.baitu.zzim.handler.WebSocketJsonHandler;
import org.baitu.zzim.handler.WebSocketProtoHandler;
import org.baitu.zzim.pojo.chat.ChatMessageOuterClass;
import org.baitu.zzim.service.ChannelManager;
import org.baitu.zzim.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @author zhangkai_a
 * @date 2025/7/1 14:55
 */
@Component
@RequiredArgsConstructor
public class NettyChannelInitializer extends ChannelInitializer<SocketChannel> {


    @Autowired
    private MessageDecoder decoder;
    @Autowired
    private MessageEncoder encoder;
    @Autowired
    private WebSocketJsonHandler webSocketJsonHandler;
    @Autowired
    private WebSocketProtoHandler webSocketProtoHandler;
    @Autowired
    private ChannelManager channelManager;
    @Autowired
    private final NettyProperties nettyProperties;
    @Autowired
    private final RedisUtil redisUtil;
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // HTTP编解码
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpObjectAggregator(65536));
        // 自定义握手jwt认证Handler，放在 WebSocketServerProtocolHandler 之前
        pipeline.addLast(new JwtHandshakeAuthHandler(channelManager,redisUtil));
        // WebSocket协议处理
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true));
        pipeline.addLast(new SimpleChannelInboundHandler<WebSocketFrame>() {
            @Override
            protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception {
                System.out.println("收到 WebSocketFrame 类型：" + msg.getClass().getSimpleName() + "message: " + msg.toString());
                ctx.fireChannelRead(msg.retain());
            }
        });
        // 消息编解码
        if (useProtobuf()) {
            // 将 WebSocket 的 BinaryWebSocketFrame 提取 ByteBuf
            pipeline.addLast(new WebSocketFrameToByteBufDecoder());

            // 使用 protobuf 反序列化 ByteBuf -> ChatMessage
            pipeline.addLast(new ProtobufDecoder(ChatMessageOuterClass.ChatMessage.getDefaultInstance()));

            // Protobuf 编码（服务端主动推送使用）
            pipeline.addLast(new WebSocketProtobufEncoder());

            // 你自己的业务逻辑 handler
            pipeline.addLast(webSocketProtoHandler);
        } else {
            pipeline.addLast(decoder);
            pipeline.addLast(encoder);

            // 业务处理
            pipeline.addLast(webSocketJsonHandler);
        }

    }

    private boolean useProtobuf() {
        // 根据配置决定使用Protobuf还是JSON
        // 示例返回，实际应从配置获取
        return nettyProperties.isUseProtobuf();
    }
}
